home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2009 February / PCWFEB09.iso / Software / Resources / Chat & Communication / Digsby build 37 / digsby_setup.exe / lib / util / perfmon.pyo (.txt) < prev    next >
Python Compiled Bytecode  |  2008-10-13  |  11KB  |  319 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyo (Python 2.5)
  3.  
  4. from __future__ import division
  5. import os
  6. import sys
  7. from util import Delegate
  8. from util.ffi import cimport
  9. from threading import Thread
  10. from ctypes import windll, WinError, byref, c_ulonglong
  11. from ctypes.wintypes import HANDLE, FILETIME
  12. from time import clock, sleep
  13. from traceback import print_exc
  14. from cStringIO import StringIO
  15. from datetime import datetime
  16. from common.commandline import where
  17. from util.threads import BackgroundThread
  18. from logging import getLogger
  19. log = getLogger('perfmon')
  20. PROCESS_QUERY_INFORMATION = 1024
  21. THREAD_QUERY_INFORMATION = 64
  22. cimport(kernel32 = [
  23.     'GetProcessTimes',
  24.     'GetThreadTimes',
  25.     'OpenProcess',
  26.     'CloseHandle',
  27.     'OpenThread'])
  28. if getattr(sys, 'DEV', False):
  29.     NUM_CONSECUTIVE_HIGHS = 5
  30. else:
  31.     NUM_CONSECUTIVE_HIGHS = 60
  32. TICK_FREQUENCY = 5
  33. PROFILE_TICKS = 15
  34. CPU_THRESHOLD = 0.95
  35. TICKS_PER_SEC = 1e+07
  36. from util.introspect import all_profilers
  37.  
  38. def enable_profilers():
  39.     profilers = all_profilers().values()
  40.     for profiler in profilers:
  41.         profiler.enable()
  42.     
  43.     _log_enabled_profilers(profilers)
  44.  
  45.  
  46. def disable_profilers():
  47.     profilers = all_profilers().values()
  48.     for profiler in profilers:
  49.         profiler.disable()
  50.     
  51.     _log_enabled_profilers(profilers)
  52.  
  53.  
  54. def _log_enabled_profilers(profilers):
  55.     len([] % ([](_[1]), len(profilers)))
  56.  
  57.  
  58. def profilers_enabled():
  59.     return all((lambda .0: for p in .0:
  60. p.enabled)(all_profilers().itervalues()))
  61.  
  62.  
  63. def get_stack_info():
  64.     io = StringIO()
  65.     where(duplicates = True, stream = io)
  66.     stack_info = io.getvalue()
  67.     return '\n\n'.join([
  68.         datetime.now().isoformat(),
  69.         stack_info])
  70.  
  71.  
  72. class CPUWatch(object):
  73.     
  74.     def usage(self, user, kernel):
  75.         return getattr(self, self.state + '_usage')(user, kernel)
  76.  
  77.     
  78.     def watching_usage(self, user, kernel):
  79.         self.user = user
  80.         self.kernel = kernel
  81.         if user + kernel >= self.threshold:
  82.             self.count += 1
  83.             log.info('cpu usage is high (not profiling yet: %s/%s): %s', self.count, NUM_CONSECUTIVE_HIGHS, user + kernel)
  84.             if self.count > NUM_CONSECUTIVE_HIGHS:
  85.                 import wx as wx
  86.                 wx.CallAfter(self.prompt_for_profiling)
  87.             
  88.         else:
  89.             self.count = 0
  90.  
  91.     
  92.     def profiling_usage(self, user, kernel):
  93.         self.user = user
  94.         self.kernel = kernel
  95.         if user + kernel >= self.threshold:
  96.             log.info('cpu usage is high: %s' % (user + kernel))
  97.             self.stack_info.append(get_stack_info())
  98.             self.count += 1
  99.             if self.count > PROFILE_TICKS:
  100.                 self.disable()
  101.                 self.send_info()
  102.             
  103.         else:
  104.             log.info('cpu usage was low again: %s' % (user + kernel))
  105.             log.info('')
  106.             self.count = 0
  107.             self.state = 'watching'
  108.  
  109.     
  110.     def disabled_usage(self, user, kernel):
  111.         pass
  112.  
  113.     
  114.     def send_info(self):
  115.         log.info('sending diagnostic information...')
  116.         Diagnostic = Diagnostic
  117.         import util.diagnostic
  118.         import wx
  119.         
  120.         try:
  121.             d = Diagnostic(description = 'CPU usage was too high.')
  122.             d.prepare_data()
  123.             if d.do_no_thread_post():
  124.                 return wx.CallAfter(wx.MessageBox, _('A log of the problem has been sent to digsby.com.\n\nThanks for helping!'), _('Diagnostic Log'))
  125.         except Exception:
  126.             print_exc()
  127.  
  128.         wx.CallAfter(wx.MessageBox, _('There was an error when submitting the diagnostic log.'))
  129.  
  130.     
  131.     def prompt_for_profiling(self):
  132.         if self._CPUWatch__in:
  133.             return None
  134.         
  135.         self._CPUWatch__in = True
  136.         log.info('prompting for profiling info')
  137.         dev = getattr(sys, 'DEV', False)
  138.         if profilers_enabled():
  139.             self.state = 'profiling'
  140.             return log.info('profiler is already enabled')
  141.         
  142.         import wx
  143.         if dev or wx.YES == wx.MessageBox(_('Digsby appears to be running slowly.\n\nDo you want to capture diagnostic information and\nsend it to digsby.com?'), _('Digsby CPU Usage'), style = wx.YES_NO | wx.ICON_ERROR):
  144.             log.info('enabling profiler')
  145.             enable_profilers()
  146.             self.count = 0
  147.             self.state = 'profiling'
  148.         else:
  149.             self.disable()
  150.         self._CPUWatch__in = False
  151.  
  152.     
  153.     def disable(self):
  154.         self.state = 'disabled'
  155.         disable_profilers()
  156.         self.cpu_monitor.done = True
  157.  
  158.     
  159.     def __init__(self, threshold = CPU_THRESHOLD):
  160.         if threshold < threshold:
  161.             pass
  162.         elif not threshold <= 1:
  163.             raise ValueError('0 < threshold <= 1')
  164.         
  165.         self.state = 'watching'
  166.         self.threshold = threshold
  167.         self.count = 0
  168.         self.ignore = False
  169.         self.cpu_monitor = CPUMonitor(self.usage)
  170.         self.cpu_monitor.start()
  171.         self._CPUWatch__in = False
  172.         self.stack_info = []
  173.  
  174.  
  175.  
  176. class CPUMonitor(BackgroundThread):
  177.     
  178.     def __init__(self, usage_cb, update_freq_secs = TICK_FREQUENCY):
  179.         BackgroundThread.__init__(self, name = 'CPUMonitor')
  180.         self.setDaemon(True)
  181.         self.done = False
  182.         self.update_freq_secs = 5
  183.         self.perfinfo = ProcessPerfInfo()
  184.         self.usage_cb = usage_cb
  185.  
  186.     
  187.     def run(self):
  188.         self.BeforeRun()
  189.         while not self.done:
  190.             self.usage_cb(*self.perfinfo.update())
  191.             sleep(self.update_freq_secs)
  192.         self.AfterRun()
  193.  
  194.  
  195.  
  196. class PerfInfo(object):
  197.     __slots__ = [
  198.         'last_update',
  199.         'handle',
  200.         'creationTime',
  201.         'exitTime',
  202.         'kernelTime',
  203.         'userTime',
  204.         'oldKernel',
  205.         'oldUser']
  206.     
  207.     def __init__(self):
  208.         self.last_update = clock()
  209.         for name in ('creationTime', 'exitTime', 'kernelTime', 'userTime', 'oldKernel', 'oldUser'):
  210.             setattr(self, name, c_ulonglong())
  211.         
  212.         self.handle = self.get_handle()
  213.         self.update()
  214.  
  215.     
  216.     def get_handle(self):
  217.         raise NotImplemented
  218.  
  219.     
  220.     def update(self):
  221.         if not self.times_func(self.handle, byref(self.creationTime), byref(self.exitTime), byref(self.kernelTime), byref(self.userTime)):
  222.             raise WinError()
  223.         
  224.         now = clock()
  225.         diff = now - self.last_update
  226.         userPercent = (self.userTime.value - self.oldUser.value) / TICKS_PER_SEC / diff
  227.         kernelPercent = (self.kernelTime.value - self.oldKernel.value) / TICKS_PER_SEC / diff
  228.         self.last_update = now
  229.         self.oldUser.value = self.userTime.value
  230.         self.oldKernel.value = self.kernelTime.value
  231.         return (userPercent, kernelPercent)
  232.  
  233.     
  234.     def __del__(self):
  235.         CloseHandle(self.handle)
  236.  
  237.  
  238.  
  239. class ProcessPerfInfo(PerfInfo):
  240.     __slots__ = []
  241.     
  242.     def __init__(self):
  243.         PerfInfo.__init__(self)
  244.  
  245.     
  246.     def get_handle(self):
  247.         return obtain_process_handle()
  248.  
  249.     
  250.     def times_func(self):
  251.         return GetProcessTimes
  252.  
  253.     times_func = property(times_func)
  254.  
  255.  
  256. class ThreadPerfInfo(PerfInfo):
  257.     __slots__ = [
  258.         'thread_id']
  259.     
  260.     def __init__(self, thread_id):
  261.         self.thread_id = thread_id
  262.         PerfInfo.__init__(self)
  263.  
  264.     
  265.     def get_handle(self):
  266.         return obtain_thread_handle(self.thread_id)
  267.  
  268.     
  269.     def times_func(self):
  270.         return GetThreadTimes
  271.  
  272.     times_func = property(times_func)
  273.  
  274.  
  275. def num_processors():
  276.     return os.environ.get('NUMBER_OF_PROCESSORS', 1)
  277.  
  278.  
  279. def obtain_process_handle(pid = None):
  280.     handle = None(OpenProcess, PROCESS_QUERY_INFORMATION, False if pid is None else pid)
  281.     if not handle:
  282.         raise WinError()
  283.     
  284.     return handle
  285.  
  286.  
  287. def obtain_thread_handle(thread_id):
  288.     handle = OpenThread(THREAD_QUERY_INFORMATION, False, thread_id)
  289.     if not handle:
  290.         raise WinError()
  291.     
  292.     return handle
  293.  
  294.  
  295. def main():
  296.     import wx
  297.     a = wx.PySimpleApp()
  298.     f = wx.Frame(None)
  299.     b = wx.Button(f, -1, 'info')
  300.     
  301.     def foo():
  302.         while True:
  303.             pass
  304.  
  305.     t = Thread(target = foo)
  306.     cpumonitor = CPUMonitor()
  307.     cpumonitor.start()
  308.     
  309.     def onbutton(e):
  310.         t.start()
  311.  
  312.     b.Bind(wx.EVT_BUTTON, onbutton)
  313.     f.Show()
  314.     a.MainLoop()
  315.  
  316. if __name__ == '__main__':
  317.     main()
  318.  
  319.